﻿using System.Security.Principal;
using Castle.Facilities.FactorySupport;
using Castle.Windsor;
using Peak.Web.Controllers.Services;
using SharpArch.Core.PersistenceSupport.NHibernate;
using SharpArch.Data.NHibernate;
using SharpArch.Core.PersistenceSupport;
using SharpArch.Web.Castle;
using Castle.MicroKernel.Registration;
using SharpArch.Core.CommonValidator;
using SharpArch.Core.NHibernateValidator.CommonValidatorAdapter;
using Peak.Web.Controllers.FormsAuthentication;

namespace Peak.Web.CastleWindsor
{
  public class ComponentRegistrar
  {
    public static void AddComponentsTo(IWindsorContainer container)
    {
      AddGenericRepositoriesTo(container);
      AddCustomRepositoriesTo(container);
      AddApplicationServicesTo(container);

      container.AddComponent("validator",
          typeof(IValidator), typeof(Validator));
      
      container.AddComponent("sessionService",
          typeof(ISessionService), typeof(SessionService));

      container.AddComponent("formsAuthenticationService",
          typeof(IFormsAuthenticationService), typeof(FormsAuthenticationService));
      
      container.AddFacility<FactorySupportFacility>();
      container.AddComponent<IPrincipalResolver, PrincipalResolver>();
      container.Register(Component.For<IPrincipal>().UsingFactory((IPrincipalResolver f) => f.Principal));              
    }

    private static void AddApplicationServicesTo(IWindsorContainer container)
    {
      container.Register(
          AllTypes.Pick()
          .FromAssemblyNamed("Peak.ApplicationServices")
          .WithService.FirstInterface());
    }

    private static void AddCustomRepositoriesTo(IWindsorContainer container)
    {
      container.Register(
          AllTypes.Pick()
          .FromAssemblyNamed("Peak.Data")
          .WithService.FirstNonGenericCoreInterface("Peak.Core"));
    }

    private static void AddGenericRepositoriesTo(IWindsorContainer container)
    {
      container.AddComponent("entityDuplicateChecker",
          typeof(IEntityDuplicateChecker), typeof(EntityDuplicateChecker));
      container.AddComponent("repositoryType",
          typeof(IRepository<>), typeof(Repository<>));
      container.AddComponent("nhibernateRepositoryType",
          typeof(INHibernateRepository<>), typeof(NHibernateRepository<>));
      container.AddComponent("repositoryWithTypedId",
          typeof(IRepositoryWithTypedId<,>), typeof(RepositoryWithTypedId<,>));
      container.AddComponent("nhibernateRepositoryWithTypedId",
          typeof(INHibernateRepositoryWithTypedId<,>), typeof(NHibernateRepositoryWithTypedId<,>));
    }
  }
}
